package roborally;

import item.*;
import item.pickable.*;
import attribute.*;

import java.io.*;
import java.util.*;

import exceptions.ProgramAnalyseError;

import program.Program;

public class Facade implements IFacade<Board, Robot, Wall, Battery, RepairKit, SurpriseBox> {

	@Override
	public Board createBoard(long width, long height) {
		return new Board(width, height);
	}

	@Override
	public void merge(Board board1, Board board2) {
		board1.merge(board2);
	}

	@Override
	public Battery createBattery(double initialEnergy, int weight) {
		return new Battery(initialEnergy, weight);
	}

	@Override
	public void putBattery(Board board, long x, long y, Battery battery) {
		battery.setValidPosition(x, y, board);		
	}

	@Override
	public long getBatteryX(Battery battery) throws IllegalStateException {
		try{
			return battery.getPosition().getX();
		}
		catch(IllegalStateException exc){
			System.out.println("This item is not on a board");
			return -1;
		}
	}

	@Override
	public long getBatteryY(Battery battery) throws IllegalStateException {
		try{
			return battery.getPosition().getY();
		}
		catch(IllegalStateException exc){
			System.out.println("This item is not on a board");
			return -1;
		}
	}

	@Override
	public Robot createRobot(int orientation, double initialEnergy) {
		return new Robot(orientation, initialEnergy);
	}

	@Override
	public void putRobot(Board board, long x, long y, Robot robot) {
		robot.setValidPosition(x, y, board);		
	}

	@Override
	public long getRobotX(Robot robot) throws IllegalStateException {
		try{
			return robot.getPosition().getX();
		}
		catch(IllegalStateException exc){
			System.out.println("This Robot is not on a board");
			return -1;
			}
	}

	@Override
	public long getRobotY(Robot robot) throws IllegalStateException {
		try{
			return robot.getPosition().getY();
		}
		catch(IllegalStateException exc){
			System.out.println("This Robot is not on a board"); //TODO
			return -1;
		}
	}

	@Override
	public int getOrientation(Robot robot) {
		return robot.getOrientation().ordinal();
	}

	@Override
	public double getEnergy(Robot robot) {
		return robot.getEnergyDoubleInWattsecond();
	}

	@Override
	public void move(Robot robot) {
		robot.move();
	}

	@Override
	public void turn(Robot robot) {
		robot.turnClockWise();
	}

	@Override
	public void counterturn(Robot robot) {
		robot.turnCounterClockWise();
	}
	

	@Override
	public int isMinimalCostToReach17Plus() {
		return 0;
	}

	@Override
	public double getMinimalCostToReach(Robot robot, long x, long y) {
		return robot.getEnergyRequiredToReach(x, y);
	}

	@Override
	public int isMoveNextTo18Plus() {
		return 0;
	}

	@Override
	public void moveNextTo(Robot robot, Robot other) {
		robot.moveNextTo(other);
	}

	@Override
	public void shoot(Robot robot){
		robot.shoot();
	}

	@Override
	public Wall createWall(){
		return new Wall();
	}

	@Override
	public void putWall(Board board, long x, long y, Wall wall){
		wall.setValidPosition(x, y, board);
	}

	@Override
	public long getWallX(Wall wall) throws IllegalStateException{
		try{
		return wall.getPosition().getX();
		}
		catch(IllegalStateException exc){
			System.out.println("This Wall is not on a board");
			return -1;
			}
		
	}

	@Override
	public long getWallY(Wall wall) throws IllegalStateException{
		try{
		return wall.getPosition().getY();
		}
		catch(IllegalStateException exc){
			System.out.println("This Wall is not on a board");
			return -1;
			}
	}

	@Override
	public ArrayList<Robot> getRobots(Board board) {
		return board.getListOfRobots();
	}

	@Override
	public ArrayList<Battery> getBatteries(Board board) {
		return board.getListOfBatteries();
	}

	@Override
	public ArrayList<Wall> getWalls(Board board){
		return board.getListOfWalls();
	}

	@Override
	public RepairKit createRepairKit(double repairAmount, int weight) {
		return new RepairKit(repairAmount, weight);
	}

	@Override
	public void putRepairKit(Board board, long x, long y, RepairKit repairKit) {
		repairKit.setValidPosition(x, y, board);	
	}

	@Override
	public long getRepairKitX(RepairKit repairKit) throws IllegalStateException {
		try{
		return repairKit.getPosition().getX();
		}
		catch(IllegalStateException exc){
			System.out.println("This RK is not on a board");
			return -1;
			}
	}

	@Override
	public long getRepairKitY(RepairKit repairKit) throws IllegalStateException {
		try{
		return repairKit.getPosition().getY();
		}
		catch(IllegalStateException exc){
			System.out.println("This RK is not on a board");
			return -1;
			}
	}

	@Override
	public SurpriseBox createSurpriseBox(int weight) {
		return new SurpriseBox(weight);
	}

	@Override
	public void putSurpriseBox(Board board, long x, long y,	SurpriseBox surpriseBox) {
		surpriseBox.setValidPosition(x, y, board);
	}

	@Override
	public long getSurpriseBoxX(SurpriseBox surpriseBox) throws IllegalStateException {
		try{
		return surpriseBox.getPosition().getX();
		}
		catch(IllegalStateException exc){
			System.out.println("This surprisebox is not on a board");
			return -1;
			}
	}

	@Override
	public long getSurpriseBoxY(SurpriseBox surpriseBox) throws IllegalStateException {
		try{
		return surpriseBox.getPosition().getY();
		}
		catch(IllegalStateException exc){
			System.out.println("This surpriseBox is not on a board");
			return -1;
			}
	}

	@Override
	public void pickUpBattery(Robot robot, Battery battery) {
		robot.pickUp(battery);
	}

	@Override
	public void useBattery(Robot robot, Battery battery) {
		robot.use(battery);
	}

	@Override
	public void dropBattery(Robot robot, Battery battery) {
		robot.drop(battery);
	}

	@Override
	public void pickUpRepairKit(Robot robot, RepairKit repairKit) {
		robot.pickUp(repairKit);
	}

	@Override
	public void useRepairKit(Robot robot, RepairKit repairKit) {
		robot.use(repairKit);
	}

	@Override
	public void dropRepairKit(Robot robot, RepairKit repairKit) {
		robot.drop(repairKit);
	}

	@Override
	public void pickUpSurpriseBox(Robot robot, SurpriseBox surpriseBox) {
		robot.pickUp(surpriseBox);
	}

	@Override
	public void useSurpriseBox(Robot robot, SurpriseBox surpriseBox) {
		robot.use(surpriseBox);
	}

	@Override
	public void dropSurpriseBox(Robot robot, SurpriseBox surpriseBox) {
		robot.drop(surpriseBox);
	}

	@Override
	public void transferItems(Robot from, Robot to) {//TODO check if OK
		from.transferTo(to);
	}

	@Override
	public ArrayList<RepairKit> getRepairKits(Board board) {
		return board.getListOfRepairKits();
	}

	@Override
	public ArrayList<SurpriseBox> getSurpriseBoxes(Board board) {
		return board.getListOfSupriseBoxes();
	}

	@Override
	public int loadProgramFromFile(Robot robot, String path) {
		Program program;
		try {
			program = Program.loadFromFile(path);
			robot.setProgram(program);
		} catch (IOException | ProgramAnalyseError e) {
			return -1;
		}
		return 0;
	}

	@Override
	public int saveProgramToFile(Robot robot, String path) {
		try {
			robot.getProgram().saveToFile(path);
		} catch (IOException e) {
			return -1;
		}
		return 0;
	}

	@Override
	public void prettyPrintProgram(Robot robot, Writer writer) {
		try {
			writer.write(robot.getProgram().prettyFormat());
		} catch (IOException e) {
			e.getMessage();
		}
	}

	@Override
	public void stepn(Robot robot, int n) {
		for(int x = 1; x < n; x++) {
			robot.executeNextBasicCommand();
		}
	}
}
